package vn.mahjonggame.game.request;

import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Timer;
import java.util.TimerTask;

import org.apache.log4j.Logger;

import vn.mahjonggame.game.Mahjong;
import vn.mahjonggame.game.MahjongExtension;
import vn.mahjonggame.metadata.GameActionType;
import vn.mahjonggame.metadata.MahjongCache;
import vn.mahjonggame.metadata.MatchState;
import vn.mahjonggame.metadata.Player;
import vn.mahjonggame.metadata.MObject;
import vn.mahjonggame.metadata.Response;
import vn.mahjonggame.metadata.TileSet;

import com.smartfoxserver.v2.entities.Room;
import com.smartfoxserver.v2.entities.User;
import com.smartfoxserver.v2.entities.data.ISFSObject;
import com.smartfoxserver.v2.entities.data.SFSObject;
import com.smartfoxserver.v2.extensions.BaseClientRequestHandler;
import com.smartfoxserver.v2.extensions.ExtensionLogLevel;

public class SkipHandler extends BaseClientRequestHandler {

	@Override
	public void handleClientRequest(User user, ISFSObject params) {
		// TODO Auto-generated method stub
		MahjongExtension ext = (MahjongExtension)getParentExtension();		
		skip(ext, user, params, false);
	}
	
	public void skip(final MahjongExtension ext,final User user,final ISFSObject params, boolean isAuto){
		setParentExtension(ext);
		final Mahjong mahjong = ext.getMahjong();
		final Player player = mahjong.getPlayerById(user.getId());
		final Room room = ext.getGameRoom();
		Logger logger = mahjong.getLogger();
		List<TileSet> skipTypes = player.getSkipTypes();
		
		logger.info(mahjong.log(room, player, GameActionType.skip.toString(), "skipTypes:" + skipTypes));
		
		String skipType = skipTypes.get(0).toString();		
		Player thrownPlayer = mahjong.getThrownPlayer();		
		Player nextPlayerOfThrownPlayer = null;		
		logger.info(mahjong.log(room, player, GameActionType.skip.toString(), "isAuto:" + isAuto));
		logger.info(mahjong.log(room, player, GameActionType.skip.toString(), "isConflict:" + player.isConflict()));
		
		if(ext.getMatchState() == MatchState.SHOW_RESULT){
			logger.info(mahjong.log(room, player, GameActionType.skip.toString(), "MatchState: " + ext.getMatchState()));
			return;
		}
				
		if(!isAuto){
			player.cancelTimer();
		}		
		
		if(thrownPlayer == null){
			nextPlayerOfThrownPlayer = mahjong.getNextPlayer(player);
		}
		else {
			nextPlayerOfThrownPlayer = mahjong.getNextPlayer(thrownPlayer);
		}
		
		mahjong.resetTileSet();
		
		Response.Builder response = new Response.Builder();
		response.turn(player.getPlayerPosition())
				.turnTime(player.getTurnTime() / 1000)
				.bonusTime(player.getBonusTime() / 1000)
				.isAuto(isAuto)
				.isConflict(player.isConflict())
				.type(skipType);		
				
		send(GameActionType.skip.toString(), response.build().getSFSObject(), user);
		
		player.setConflict(false);
		nextPlayerOfThrownPlayer.setHasThrown(false);		
		nextPlayerOfThrownPlayer.setHasPicked(false);		
		
		logger.info(mahjong.log(room, player, GameActionType.skip.toString(), "nextTurn: " + player.getPlayerPosition() + " skipType: " + skipType));
		logger.info(mahjong.log(room, player, GameActionType.skip.toString(), "Send skip cmd"));
		
		/*
		 * Reset player's state
		 *
		List<User> users = room.getUserList();
		if(skipType.equalsIgnoreCase(TileSet.RON.toString())){			
			callKan(ext, mahjong, users, room, player);
			callPon(ext, mahjong, users, room, player);
			callChi(ext, mahjong, users, room, player);
		}
		else if(skipType.equalsIgnoreCase(TileSet.OPENKAN.toString())){					
			callPon(ext, mahjong, users, room, player);
			callChi(ext, mahjong, users, room, player);
		}
		else if(skipType.equalsIgnoreCase(TileSet.PON.toString())){			
			/*
			 * call CHi if another player is waiting for CHI and no one else can call RON
			 *
			callChi(ext, mahjong, users, room, player);			
		}
		*/
		
		if(skipType.equalsIgnoreCase(TileSet.RIICHI.toString()) || skipType.equalsIgnoreCase(TileSet.TSUMO.toString())){
			
			
			if(skipType.equalsIgnoreCase(TileSet.TSUMO.toString())){
				player.setTsumo(false);
			}
			
			final Response.Builder nextParams = new Response.Builder();					
			int leftTileSize = player.getLeftTiles().size();
			nextParams.tile(player.getLeftTiles().get(leftTileSize - 1).getId());			
			Timer timer = player.getTimer();			
			int delay = player.getBonusTime() + player.getTurnTime();
			logger.info(mahjong.log(room, player, GameActionType.skip.toString(), "skipType: " + skipType));
			logger.info(mahjong.log(room, player, GameActionType.skip.toString(), "Calling throw handler: " + delay));
			timer.schedule(new TimerTask() {
				  @Override
				  public void run() {
					  if(!player.isHasThrown()){
						  ThrowTileHandler throwTileHandler = new ThrowTileHandler();					  
						  throwTileHandler.throwTile(ext, user, nextParams.build().getSFSObject(), true, false);
					  }								
				  }
			}, delay);
		}
		
		/*
		 * If 0 and 1 is disconnected,2 can call RON, 3 throw a tile which can make the 2 can call RON, if 2 cancel RON, need to pick for 1 automatically 
		 */
		if (nextPlayerOfThrownPlayer.isDisconnect()){
			logger.info(mahjong.log(room, player, GameActionType.skip.toString(), "Calling pick handler..."));
			PickTileHandler pickTileHandler = new PickTileHandler();
			pickTileHandler.pickTile(ext, user, params, false);
		}
	}
	
	public void callChi(MahjongExtension ext, Mahjong mahjong, List<User> users, Room room, Player player, Logger logger){
		
		if(mahjong.getCallingChiPlayer() == null) return;
		
		Map playerCache = player.getCache();
		
		Response.Builder chiResponse = new Response.Builder();
		chiResponse.bonusTime(Integer.valueOf(String.valueOf(playerCache.get(MObject.bonusTime.toString()))))
					.chiTiles((Collection<Integer>)playerCache.get(MObject.chiTiles.toString()));
		
		playerCache.remove(MObject.bonusTime.toString());
		playerCache.remove(MObject.chiTiles.toString());
		
		Player callingPlayer = mahjong.getCallingChiPlayer();
		User callingChiUser = mahjong.getUserByPlayerId(callingPlayer.getPlayerId(), users);
		
		CallChiHandler callChiHandler = new CallChiHandler();
		callChiHandler.callChi(ext, callingChiUser, chiResponse.build().getSFSObject());
				
		logger.info(mahjong.log(room, player, GameActionType.skip.toString(), "Call CHI for the waiting player " + callingPlayer.toString()));		
	}
	
	public void callPon(MahjongExtension ext, Mahjong mahjong, List<User> users, Room room, Player player, Logger logger){
		if(mahjong.getCallingPonPlayer() == null) return;
		
		Map playerCache = player.getCache();
		
		Response.Builder ponResponse = new Response.Builder();
		ponResponse.bonusTime(Integer.valueOf(String.valueOf(playerCache.get(MObject.bonusTime.toString()))))
					.tile(Integer.valueOf(String.valueOf(playerCache.get(MObject.tile.toString()))));
		
		playerCache.remove(MObject.bonusTime.toString());
		playerCache.remove(MObject.tile.toString());
		
		Player callingPlayer = mahjong.getCallingChiPlayer();
		User callingChiUser = mahjong.getUserByPlayerId(callingPlayer.getPlayerId(), users);
		
		CallPonHandler callPonHandler = new CallPonHandler();
		callPonHandler.callPon(ext, callingChiUser, ponResponse.build().getSFSObject());
		
		logger.info(mahjong.log(room, player, GameActionType.skip.toString(), "Call PON for the waiting player " + callingPlayer.toString()));
	}
	
	public void callKan(MahjongExtension ext, Mahjong mahjong, List<User> users, Room room, Player player, Logger logger){
		if(mahjong.getCallingOpenKanPlayer() == null) return;
		
		Map playerCache = player.getCache();
		
		Response.Builder kanResponse = new Response.Builder();
		kanResponse.bonusTime(Integer.valueOf(String.valueOf(playerCache.get(MObject.bonusTime.toString()))))
					.tile(Integer.valueOf(String.valueOf(playerCache.get(MObject.tile.toString()))))
					.kanType(String.valueOf(playerCache.get(MObject.kanType.toString())));
		
		playerCache.remove(MObject.bonusTime.toString());
		playerCache.remove(MObject.tile.toString());
		playerCache.remove(MObject.kanType.toString());
		
		Player callingPlayer = mahjong.getCallingChiPlayer();
		User callingChiUser = mahjong.getUserByPlayerId(callingPlayer.getPlayerId(), users);
		
		CallKanHandler callKanHandler = new CallKanHandler();
		callKanHandler.callKan(ext, callingChiUser, kanResponse.build().getSFSObject());
		
		logger.info(mahjong.log(room, player, GameActionType.skip.toString(), "Call KAN for the waiting player " + callingPlayer.toString()));
	}
	
}
